package com.yc.cloud.portal.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.yc.cloud.common.basic.api.ResponseResult;
import com.yc.cloud.common.basic.utils.MyFileUtils;
import com.yc.cloud.common.basic.utils.PathUtils;
import com.yc.cloud.entity.DeviceCaptureLogs;
import com.yc.cloud.entity.DeviceGpsLogs;
import com.yc.cloud.entity.DeviceOcrLogs;
import com.yc.cloud.entity.DeviceStatusLogs;
import com.yc.cloud.portal.common.HSResponseResult;
import com.yc.cloud.portal.request.MediaBasicInfoParam;
import com.yc.cloud.portal.request.MediaCaptureParam;
import com.yc.cloud.portal.request.MediaLocationInfoParam;
import com.yc.cloud.portal.request.MediaOcrInfoParam;
import com.yc.cloud.portal.service.*;
import com.yc.cloud.portal.utils.HSRequestManager;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.nio.file.Paths;
import java.time.LocalDateTime;

@Service
@Slf4j
public class MediaServiceImpl implements MediaService {

    private final int SUCCESS_CODE = 200;

    private final PathUtils pathUtils;

    private final DeviceStatusLogsService arDeviceStatusService;

    private final DeviceCaptureLogsService deviceCaptureLogsService;

    private final DeviceOcrLogsService deviceOcrLogsService;

    private final DeviceGpsLogsService deviceGpsLogsService;

    private final ARPathService arPathService;

    private final HSRequestManager hsRequestManager;

    public MediaServiceImpl(PathUtils pathUtils, DeviceStatusLogsService arDeviceStatusService, DeviceCaptureLogsService deviceCaptureLogsService, DeviceOcrLogsService deviceOcrLogsService, DeviceGpsLogsService deviceGpsLogsService, ARPathService arPathService, HSRequestManager hsRequestManager) {
        this.pathUtils = pathUtils;
        this.arDeviceStatusService = arDeviceStatusService;
        this.deviceCaptureLogsService = deviceCaptureLogsService;
        this.deviceOcrLogsService = deviceOcrLogsService;
        this.deviceGpsLogsService = deviceGpsLogsService;
        this.arPathService = arPathService;
        this.hsRequestManager = hsRequestManager;
    }

    @Override
    public ResponseResult<String> basicInfo(MediaBasicInfoParam param) {
        //保存信息到数据库
        val arDeviceStatusEntity = new DeviceStatusLogs();
        BeanUtils.copyProperties(param, arDeviceStatusEntity);
        arDeviceStatusEntity.setCreateTime(LocalDateTime.now());
        val saveFlag = arDeviceStatusService.save(arDeviceStatusEntity);
        if (!saveFlag) {
            log.error("保存设备状态失败");
        }
        val result = hsRequestManager.basicInfo(param.getDeviceNum(), param.getDeviceType(), param.getState());
        if (StrUtil.isEmpty(result)) {
            return ResponseResult.failed("AR眼镜发送设备状态失败");
        }
        val response = JSONUtil.toBean(result, HSResponseResult.class);
        if (response.getCode() != SUCCESS_CODE) {
            return ResponseResult.failed(response.getMsg());
        }
        return ResponseResult.success();
    }

    @Override
    public ResponseResult<String> capture(MediaCaptureParam param, MultipartFile file) {
        // 保存图片到临时目录,可以保存也不可以不保存,主要用于留存
        var suffix = FileUtil.getSuffix(param.getPicName());
        // 图片后缀名为空则默认为png
        if (StrUtil.isEmpty(suffix)) {
            suffix = "png";
        }
        val newFileName = FileUtil.getPrefix(param.getPicName()) + "." + suffix;
        val picPath = Paths.get(pathUtils.getBasePath(), param.getDeviceNum(), newFileName).toString();
        // 保存图片到本地,去除前缀
        val newBase64PicString = param.getPicString().replaceAll("data:image/\\w+;base64,", "");
        MyFileUtils.decodeAndSaveFile(newBase64PicString, picPath);

        //将抓拍记录保存到本地数据库中做留存
        saveCaptureInfoToDb(param, picPath);

        val result = hsRequestManager.capture(param);
        if (StrUtil.isEmpty(result)) {
            return ResponseResult.failed("capture失败");
        }
        val response = JSONUtil.toBean(result, HSResponseResult.class);
        if (response.getCode() != SUCCESS_CODE) {
            return ResponseResult.failed(response.getMsg());
        }
        return ResponseResult.success();
    }

    /**
     * 保存抓拍记录到本地数据库中
     *
     * @param param   抓拍参数
     * @param picPath 图片路径
     */
    private void saveCaptureInfoToDb(MediaCaptureParam param, String picPath) {
        val captureInfoLogs = new DeviceCaptureLogs();
        BeanUtils.copyProperties(param, captureInfoLogs);
        captureInfoLogs.setPicPath(picPath);
        captureInfoLogs.setCreateTime(LocalDateTime.now());
        val saveFlag = deviceCaptureLogsService.save(captureInfoLogs);
        if (!saveFlag) {
            log.error("保存抓拍记录到数据库失败");
        }
    }


    @Override
    public ResponseResult<String> ocrInfo(MediaOcrInfoParam param) {
        // 保存OCR记录到本地数据库中做留存
        saveOcrInfoToDb(param);

        val result = hsRequestManager.ocrInfo(param);
        if (StrUtil.isEmpty(result)) {
            return ResponseResult.failed("ocrInfo失败");
        }
        val response = JSONUtil.toBean(result, HSResponseResult.class);
        if (response.getCode() != SUCCESS_CODE) {
            return ResponseResult.failed(response.getMsg());
        }
        return ResponseResult.success();
    }

    /**
     * 保存OCR记录到本地数据库中
     *
     * @param param OCR参数,其中通过文件名称找到当时OCR的图片路径
     */
    private void saveOcrInfoToDb(MediaOcrInfoParam param) {
        val ocrInfoLogs = new DeviceOcrLogs();
        BeanUtils.copyProperties(param, ocrInfoLogs);
        val ocrPicFile = arPathService.getOcrFilePath(param.getDeviceNum(), param.getOcrFileName());
        ocrInfoLogs.setPicPath(ocrPicFile.getAbsolutePath());
        ocrInfoLogs.setCreateTime(LocalDateTime.now());
        val saveFlag = deviceOcrLogsService.save(ocrInfoLogs);
        if (!saveFlag) {
            log.error("保存OCR记录到数据库失败");
        }
    }

    @Override
    public ResponseResult<String> locationInfo(MediaLocationInfoParam param) {
        saveLocationInfoToDb(param);
        val result = hsRequestManager.locationInfo(param);
        if (StrUtil.isEmpty(result)) {
            return ResponseResult.failed("locationInfo失败");
        }
        val response = JSONUtil.toBean(result, HSResponseResult.class);
        if (response.getCode() != SUCCESS_CODE) {
            return ResponseResult.failed(response.getMsg());
        }
        return ResponseResult.success();
    }

    /**
     * 保存位置信息到本地数据库中
     *
     * @param param 位置信息参数
     */
    private void saveLocationInfoToDb(MediaLocationInfoParam param) {
        val locationInfoLogs = new DeviceGpsLogs();
        BeanUtils.copyProperties(param, locationInfoLogs);
        locationInfoLogs.setCreateTime(LocalDateTime.now());
        val saveFlag = deviceGpsLogsService.save(locationInfoLogs);
        if (!saveFlag) {
            log.error("保存位置信息到数据库失败");
        }
    }

}
